//
//  MyRecord.h
//  RandomForest-AndreaBalboni
//
//  Created by Andrea Balboni on 05/04/12.
//  Copyright (c) 2012 Università degli Studi di Modena e Reggio Emilia. All rights reserved.
//

#ifndef RandomForest_AndreaBalboni_MyRecord_h
#define RandomForest_AndreaBalboni_MyRecord_h

#include <vector>
#include <map>
#include <iostream>
#include <algorithm>


template <typename _T>
class MyRecord {
private:
    int _class;
    std::vector<_T> _featureVector;
    
    
public:
    
    //Costruttore
    MyRecord() : _class(-1), _featureVector(0){}
    
    //Costruttore che ridimensiona anche il featureVector alla dimensionalita' delle features.
    MyRecord(unsigned int featureSpaceDimension):_class(-1),_featureVector(featureSpaceDimension){}
    
    //Costruttore che inizializza il featureVector
    MyRecord(std::vector<_T> featureVector, int classe): _featureVector(featureVector), _class(classe) {}
    
    //Restituisco la Classe del record
    int getClass() const{
        return _class;
    }
    
    //Imposto la Classe del record
    void setClass(int classe){
        _class=classe;
    }
    
    //Restituisco una reference al valore di una Feature dato l'indice nel featureVector
    _T& getFeature(int i){
        return _featureVector[i];
    }
    
    
    //Operatore per l'accesso in scrittura in una posizione del featureVector
    _T& operator()(int index){
        return _featureVector[index];
    }
    
    //Operatore per l'accesso in lettura in una posizione del featureVector
    const _T& operator()(int index) const{
        return _featureVector[index];
    }
    
    //Restituisco una reference al featureVector
    std::vector<_T>& getFeatureVector() const{
        return _featureVector;
    }
    
    //Svuoto il featureVector
    void clearFeatureVector(){
        _featureVector.clear();
    }
    
    //Ridimensiono il featureVector
    void resizeFeatureVector(unsigned int size){
        _featureVector.resize(size);
    }
    
    //Copio nel featureVector i valori da un altro vettore
    void setFeatureVector(std::vector<_T> &featureVector)
    {
        _featureVector.resize(featureVector.size());
        std::copy(featureVector.begin(),featureVector.end(), _featureVector.begin());
    }
    
    //Restituisco una reference al valore della massima feature all'interno del featureVector
    _T& getMaxFeature(){
        return *max_element(_featureVector.begin(),_featureVector.end());
    }
    
    
    //Restituisco la posizione del valore massimo all'interno del featureVector
    int getMaxFeaturePos(){
        return std::distance(_featureVector.begin(),max_element(_featureVector.begin(),_featureVector.end()));
    }
    
    //Restituisco una reference al valore minimo all'interno del featureVector
    _T& getMinFeature(){
        return *min_element(_featureVector.begin(),_featureVector.end());
    }
    
    //Restituisco la posizione del valore minimo all'interno del featureVector
    int getMinFeaturePos(){
        return std::distance(_featureVector.begin(),min_element(_featureVector.begin(),_featureVector.end()));
    }
    
    //Restituisco la dimensione del featueVector
    int getSize(){
        return _featureVector.size();
    }
    
    //Calcolo la distribuzione dei valori delle fatures all'interno del record.
    std::map<_T,double> valuesProbDist() {
        std::map<_T,double> h;
        typedef typename std::vector<_T>::iterator viter;
        typedef typename std::map<_T,double>::iterator hiter;
        int numfeatures=getSize();
        for(viter it=_featureVector.begin();it!=_featureVector.end();++it){
            hiter hit=h.find(*it);
            if(hit!=h.end()){
                hit->second++;
            }else{
                h.insert(std::pair<_T, double>(*it,1));
            }
        }
        
        
        for(hiter it=h.begin();it!=h.end();++it){
            it->second/=(double)(numfeatures);
        }
        return h;
    }
   
    
};

#endif
